import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Address;
import org.fisco.bcos.sdk.abi.datatypes.Bool;
import org.fisco.bcos.sdk.abi.datatypes.DynamicArray;
import org.fisco.bcos.sdk.abi.datatypes.Event;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple3;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple4;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple5;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple8;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.eventsub.EventCallback;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class AgriculturalTraceability extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550614117806100606000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630f0c782e146100bf57806332e086a1146100e857806336605968146101115780635446196a1461014e578063663c01af1461017757806368111cce146101a25780637cc1f867146101e6578063848373f3146102125780638da5cb5b1461023b578063b3af7f0314610266578063de5ed1931461028f578063f2fde38b146102b8575b600080fd5b3480156100cb57600080fd5b506100e660048036036100e1919081019061373c565b6102e1565b005b3480156100f457600080fd5b5061010f600480360361010a9190810190613893565b6106e4565b005b34801561011d57600080fd5b5061013860048036036101339190810190613893565b610b3d565b6040516101459190613d61565b60405180910390f35b34801561015a57600080fd5b50610175600480360361017091908101906137fc565b61166f565b005b34801561018357600080fd5b5061018c611f74565b6040516101999190613d3f565b60405180910390f35b3480156101ae57600080fd5b506101c960048036036101c491908101906136fb565b61224d565b6040516101dd989796959493929190613dd5565b60405180910390f35b3480156101f257600080fd5b506101fb6128b2565b604051610209929190613d16565b60405180910390f35b34801561021e57600080fd5b5061023960048036036102349190810190613790565b6128e8565b005b34801561024757600080fd5b50610250612c1e565b60405161025d9190613cd2565b60405180910390f35b34801561027257600080fd5b5061028d600480360361028891908101906136fb565b612c43565b005b34801561029b57600080fd5b506102b660048036036102b19190810190613790565b612ed8565b005b3480156102c457600080fd5b506102df60048036036102da91908101906136d2565b613233565b005b600080836001816040518082805190602001908083835b60208310151561031d57805182526020820191506020810190506020830392506102f8565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060060160009054906101000a900460ff1615156103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039990613e76565b60405180910390fd5b6001816040518082805190602001908083835b6020831015156103da57805182526020820191506020810190506020830392506103b5565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060060160159054906101000a900460ff16151515610460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045790613f76565b60405180910390fd5b6001856040518082805190602001908083835b6020831015156104985780518252602082019150602081019050602083039250610473565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902092508260060160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610561576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161055890613ed6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141515156105d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ca90613e96565b60405180910390fd5b8260060160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150838360060160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846040518082805190602001908083835b602083101515610673578051825260208201915060208101905060208303925061064e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020600019167fc3135e905b08ec3ba30d6daac29842fda6c6185ca49a9fd6a447eb3cff3b5b1d85846040516106d5929190613ced565b60405180910390a25050505050565b6106ec6133f4565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613eb6565b60405180910390fd5b6001866040518082805190602001908083835b6020831015156107b55780518252602082019150602081019050602083039250610790565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060060160009054906101000a900460ff1615151561083b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083290613f16565b60405180910390fd5b600188888888886040518087805190602001908083835b602083101515610878578051825260208201915060208101905060208303925061084e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390a2505050565b60006108a082613ffc565b808452602084019350836020820285016108b985613fef565b60005b848110156108f75783830388526108d9838351613a2c565b92506108e48261401d565b91506020880197506001810190506108c2565b5081965050505050505090565b61090c8161404a565b82525050565b600061091d82614012565b808452610931816020860160208601614099565b61093a816140cc565b602085010191505092915050565b600061095382614007565b808452610967816020860160208601614099565b610970816140cc565b602085010191505092915050565b6000601682527f50726f6475637420646f6573206e6f74206578697374000000000000000000006020830152604082019050919050565b6000601582527f496e76616c6964206275796572206164647265737300000000000000000000006020830152604082019050919050565b6000602182527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f60208301527f6e000000000000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000602b82527f4f6e6c79207468652063757272656e74206f776e65722063616e2073656c6c2060208301527f7468652070726f647563740000000000000000000000000000000000000000006040830152606082019050919050565b6000601782527f496e76616c6964206669656c6420746f207570646174650000000000000000006020830152604082019050919050565b6000601682527f50726f6475637420616c726561647920657869737473000000000000000000006020830152604082019050919050565b6000601682527f50726f64756374206973206e6f742064656c65746564000000000000000000006020830152604082019050919050565b6000602482527f4e6577206f776e65722063616e6e6f7420626520746865207a65726f2061646460208301527f72657373000000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601882527f50726f6475637420686173206265656e2064656c6574656400000000000000006020830152604082019050919050565b613ccc81614056565b82525050565b6000602082019050613ce7600083018461396a565b92915050565b6000604082019050613d02600083018561396a565b613d0f602083018461396a565b9392505050565b6000604082019050613d2b600083018561396a565b613d386020830184613cc3565b9392505050565b60006020820190508181036000830152613d598184613979565b90508181036020830152613d7660008301846139e7565b9291505050565b60006020820190508181036000830152613d9681856139f6565b90508181036020830152613dcc81846139f6565b9050939250505050565b6000610100820190508181036000830152613df0818b6139f6565b90508181036020830152613e04818a6139f6565b90508181036040830152613e1881896139f6565b9050613e276060830188613cc3565b8181036080830152613e3981876139f6565b905081810360a0830152613e4d8186613979565b9050613e5c60c083018561396a565b613e6960e08301846139e7565b9998505050505050505050565b60006020820190508181036000830152613e8f81613a62565b9050919050565b60006020820190508181036000830152613eaf81613a99565b9050919050565b60006020820190508181036000830152613ecf81613ad0565b9050919050565b60006020820190508181036000830152613eef81613b2d565b9050919050565b60006020820190508181036000830152613f0f81613b8a565b9050919050565b60006020820190508181036000830152613f2f81613bc1565b9050919050565b60006020820190508181036000830152613f4f81613bf8565b9050919050565b60006020820190508181036000830152613f6f81613c2f565b9050919050565b600060405190508181","0181811067ffffffffffffffff82111715613fb957600080fd5b8060405250919050565b600067ffffffffffffffff821115613fda57600080fd5b601f19601f8301169050602081019050919050565b6000602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156140b757808201518184015260208101905061409c565b838111156140c6576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a723058203b9a9ad20d02e10daaad288fee55d1a02a9cb862a700e0a18ef6c850bf4530196c6578706572696d656e74616cf50037"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_buyer\",\"type\":\"address\"}],\"name\":\"purchaseProduct\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_name\",\"type\":\"string\"},{\"name\":\"_producer\",\"type\":\"string\"},{\"name\":\"_productionDate\",\"type\":\"uint256\"},{\"name\":\"_origin\",\"type\":\"string\"}],\"name\":\"createProduct\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_name\",\"type\":\"string\"},{\"name\":\"_producer\",\"type\":\"string\"},{\"name\":\"_productionDate\",\"type\":\"uint256\"},{\"name\":\"_origin\",\"type\":\"string\"}],\"name\":\"verifyDataIntegrity\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_field\",\"type\":\"string\"},{\"name\":\"_value\",\"type\":\"string\"}],\"name\":\"updateProductInfo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllProductIds\",\"outputs\":[{\"name\":\"\",\"type\":\"string[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"}],\"name\":\"getProduct\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string[]\"},{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getContractInfo\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_reason\",\"type\":\"string\"}],\"name\":\"deleteProduct\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"}],\"name\":\"restoreProduct\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_id\",\"type\":\"string\"},{\"name\":\"_inspectionInfo\",\"type\":\"string\"}],\"name\":\"addInspection\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"producer\",\"type\":\"string\"}],\"name\":\"ProductCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"inspectionInfo\",\"type\":\"string\"}],\"name\":\"InspectionAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"field\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"string\"}],\"name\":\"ProductUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"buyer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"seller\",\"type\":\"address\"}],\"name\":\"ProductPurchased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"ProductDeleted\",\"type\":\"event\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_PURCHASEPRODUCT = "purchaseProduct";

    public static final String FUNC_CREATEPRODUCT = "createProduct";

    public static final String FUNC_VERIFYDATAINTEGRITY = "verifyDataIntegrity";

    public static final String FUNC_UPDATEPRODUCTINFO = "updateProductInfo";

    public static final String FUNC_GETALLPRODUCTIDS = "getAllProductIds";

    public static final String FUNC_GETPRODUCT = "getProduct";

    public static final String FUNC_GETCONTRACTINFO = "getContractInfo";

    public static final String FUNC_DELETEPRODUCT = "deleteProduct";

    public static final String FUNC_OWNER = "owner";

    public static final String FUNC_RESTOREPRODUCT = "restoreProduct";

    public static final String FUNC_ADDINSPECTION = "addInspection";

    public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership";

    public static final String FUNC_GETOWNERSHIPTRANSFER = "getOwnershipTransfer";

    public static final Event PRODUCTCREATED_EVENT = new Event("ProductCreated", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>(true) {}, new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
    ;

    public static final Event INSPECTIONADDED_EVENT = new Event("InspectionAdded", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>(true) {}, new TypeReference<Utf8String>() {}));
    ;

    public static final Event PRODUCTUPDATED_EVENT = new Event("ProductUpdated", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>(true) {}, new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
    ;

    public static final Event OWNERSHIPTRANSFERRED_EVENT = new Event("OwnershipTransferred", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Address>(true) {}, new TypeReference<Bytes32>(true) {}));
    ;

    public static final Event PRODUCTPURCHASED_EVENT = new Event("ProductPurchased", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>(true) {}, new TypeReference<Address>() {}, new TypeReference<Address>() {}));
    ;

    public static final Event PRODUCTDELETED_EVENT = new Event("ProductDeleted", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>(true) {}, new TypeReference<Utf8String>() {}));
    ;

    protected AgriculturalTraceability(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public TransactionReceipt purchaseProduct(String _id, String _buyer) {
        final Function function = new Function(
                FUNC_PURCHASEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Address(_buyer)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] purchaseProduct(String _id, String _buyer, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_PURCHASEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Address(_buyer)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForPurchaseProduct(String _id, String _buyer) {
        final Function function = new Function(
                FUNC_PURCHASEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Address(_buyer)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<String, String> getPurchaseProductInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_PURCHASEPRODUCT, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Address>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue()
                );
    }

    public TransactionReceipt createProduct(String _id, String _name, String _producer, BigInteger _productionDate, String _origin) {
        final Function function = new Function(
                FUNC_CREATEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_producer), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_productionDate), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_origin)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] createProduct(String _id, String _name, String _producer, BigInteger _productionDate, String _origin, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_CREATEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_producer), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_productionDate), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_origin)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForCreateProduct(String _id, String _name, String _producer, BigInteger _productionDate, String _origin) {
        final Function function = new Function(
                FUNC_CREATEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_producer), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_productionDate), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_origin)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple5<String, String, String, BigInteger, String> getCreateProductInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_CREATEPRODUCT, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple5<String, String, String, BigInteger, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (String) results.get(2).getValue(), 
                (BigInteger) results.get(3).getValue(), 
                (String) results.get(4).getValue()
                );
    }

    public Boolean verifyDataIntegrity(String _id, String _name, String _producer, BigInteger _productionDate, String _origin) throws ContractException {
        final Function function = new Function(FUNC_VERIFYDATAINTEGRITY, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_producer), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_productionDate), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_origin)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Bool>() {}));
        return executeCallWithSingleValueReturn(function, Boolean.class);
    }

    public TransactionReceipt updateProductInfo(String _id, String _field, String _value) {
        final Function function = new Function(
                FUNC_UPDATEPRODUCTINFO, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_field), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_value)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] updateProductInfo(String _id, String _field, String _value, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_UPDATEPRODUCTINFO, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_field), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_value)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForUpdateProductInfo(String _id, String _field, String _value) {
        final Function function = new Function(
                FUNC_UPDATEPRODUCTINFO, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_field), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_value)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple3<String, String, String> getUpdateProductInfoInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_UPDATEPRODUCTINFO, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple3<String, String, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (String) results.get(2).getValue()
                );
    }

    public List getAllProductIds() throws ContractException {
        final Function function = new Function(FUNC_GETALLPRODUCTIDS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<DynamicArray<Utf8String>>() {}));
        List<Type> result = (List<Type>) executeCallWithSingleValueReturn(function, List.class);
        return convertToNative(result);
    }

    public Tuple8<String, String, String, BigInteger, String, List<String>, String, Boolean> getProduct(String _id) throws ContractException {
        final Function function = new Function(FUNC_GETPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}, new TypeReference<DynamicArray<Utf8String>>() {}, new TypeReference<Address>() {}, new TypeReference<Bool>() {}));
        List<Type> results = executeCallWithMultipleValueReturn(function);
        return new Tuple8<String, String, String, BigInteger, String, List<String>, String, Boolean>(
                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (String) results.get(2).getValue(), 
                (BigInteger) results.get(3).getValue(), 
                (String) results.get(4).getValue(), 
                convertToNative((List<Utf8String>) results.get(5).getValue()), 
                (String) results.get(6).getValue(), 
                (Boolean) results.get(7).getValue());
    }

    public Tuple2<String, BigInteger> getContractInfo() throws ContractException {
        final Function function = new Function(FUNC_GETCONTRACTINFO, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = executeCallWithMultipleValueReturn(function);
        return new Tuple2<String, BigInteger>(
                (String) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue());
    }

    public TransactionReceipt deleteProduct(String _id, String _reason) {
        final Function function = new Function(
                FUNC_DELETEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_reason)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] deleteProduct(String _id, String _reason, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_DELETEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_reason)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForDeleteProduct(String _id, String _reason) {
        final Function function = new Function(
                FUNC_DELETEPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_reason)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<String, String> getDeleteProductInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_DELETEPRODUCT, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue()
                );
    }

    public String owner() throws ContractException {
        final Function function = new Function(FUNC_OWNER, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public TransactionReceipt restoreProduct(String _id) {
        final Function function = new Function(
                FUNC_RESTOREPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] restoreProduct(String _id, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_RESTOREPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForRestoreProduct(String _id) {
        final Function function = new Function(
                FUNC_RESTOREPRODUCT, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple1<String> getRestoreProductInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_RESTOREPRODUCT, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<String>(

                (String) results.get(0).getValue()
                );
    }

    public TransactionReceipt addInspection(String _id, String _inspectionInfo) {
        final Function function = new Function(
                FUNC_ADDINSPECTION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_inspectionInfo)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] addInspection(String _id, String _inspectionInfo, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_ADDINSPECTION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_inspectionInfo)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForAddInspection(String _id, String _inspectionInfo) {
        final Function function = new Function(
                FUNC_ADDINSPECTION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_id), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_inspectionInfo)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<String, String> getAddInspectionInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_ADDINSPECTION, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue()
                );
    }

    public TransactionReceipt transferOwnership(String newOwner) {
        final Function function = new Function(
                FUNC_TRANSFEROWNERSHIP, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(newOwner)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] transferOwnership(String newOwner, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_TRANSFEROWNERSHIP, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(newOwner)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransactionWithByteReturn(function, callback);
    }

    public String getSignedTransactionForTransferOwnership(String newOwner) {
        final Function function = new Function(
                FUNC_TRANSFEROWNERSHIP, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(newOwner)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple1<String> getTransferOwnershipInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_TRANSFEROWNERSHIP, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<String>(

                (String) results.get(0).getValue()
                );
    }

    public List<ProductCreatedEventResponse> getProductCreatedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(PRODUCTCREATED_EVENT, transactionReceipt);
        ArrayList<ProductCreatedEventResponse> responses = new ArrayList<ProductCreatedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            ProductCreatedEventResponse typedResponse = new ProductCreatedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.id = (byte[]) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.name = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.producer = (String) eventValues.getNonIndexedValues().get(1).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeProductCreatedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTCREATED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeProductCreatedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTCREATED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<InspectionAddedEventResponse> getInspectionAddedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(INSPECTIONADDED_EVENT, transactionReceipt);
        ArrayList<InspectionAddedEventResponse> responses = new ArrayList<InspectionAddedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            InspectionAddedEventResponse typedResponse = new InspectionAddedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.id = (byte[]) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.inspectionInfo = (String) eventValues.getNonIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeInspectionAddedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(INSPECTIONADDED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeInspectionAddedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(INSPECTIONADDED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<ProductUpdatedEventResponse> getProductUpdatedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(PRODUCTUPDATED_EVENT, transactionReceipt);
        ArrayList<ProductUpdatedEventResponse> responses = new ArrayList<ProductUpdatedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            ProductUpdatedEventResponse typedResponse = new ProductUpdatedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.id = (byte[]) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.field = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.value = (String) eventValues.getNonIndexedValues().get(1).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeProductUpdatedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTUPDATED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeProductUpdatedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTUPDATED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<OwnershipTransferredEventResponse> getOwnershipTransferredEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt);
        ArrayList<OwnershipTransferredEventResponse> responses = new ArrayList<OwnershipTransferredEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.newOwner = (String) eventValues.getIndexedValues().get(1).getValue();
            typedResponse.txHash = (byte[]) eventValues.getIndexedValues().get(2).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeOwnershipTransferredEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeOwnershipTransferredEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<ProductPurchasedEventResponse> getProductPurchasedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(PRODUCTPURCHASED_EVENT, transactionReceipt);
        ArrayList<ProductPurchasedEventResponse> responses = new ArrayList<ProductPurchasedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            ProductPurchasedEventResponse typedResponse = new ProductPurchasedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.id = (byte[]) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.buyer = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.seller = (String) eventValues.getNonIndexedValues().get(1).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeProductPurchasedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTPURCHASED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeProductPurchasedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTPURCHASED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<ProductDeletedEventResponse> getProductDeletedEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(PRODUCTDELETED_EVENT, transactionReceipt);
        ArrayList<ProductDeletedEventResponse> responses = new ArrayList<ProductDeletedEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            ProductDeletedEventResponse typedResponse = new ProductDeletedEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.id = (byte[]) eventValues.getIndexedValues().get(0).getValue();
            typedResponse.reason = (String) eventValues.getNonIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeProductDeletedEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTDELETED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeProductDeletedEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(PRODUCTDELETED_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public Tuple4<String, String, byte[], BigInteger> getOwnershipTransfer(byte[] _txHash) throws ContractException {
        final Function function = new Function(FUNC_GETOWNERSHIPTRANSFER, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32(_txHash)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}, new TypeReference<Bytes32>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = executeCallWithMultipleValueReturn(function);
        return new Tuple4<String, String, byte[], BigInteger>(
                (String) results.get(0).getValue(),
                (String) results.get(1).getValue(),
                (byte[]) results.get(2).getValue(),
                (BigInteger) results.get(3).getValue());
    }

    public static AgriculturalTraceability load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new AgriculturalTraceability(contractAddress, client, credential);
    }

    public static AgriculturalTraceability deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(AgriculturalTraceability.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }

    public static class ProductCreatedEventResponse {
        public TransactionReceipt.Logs log;

        public byte[] id;

        public String name;

        public String producer;
    }

    public static class InspectionAddedEventResponse {
        public TransactionReceipt.Logs log;

        public byte[] id;

        public String inspectionInfo;
    }

    public static class ProductUpdatedEventResponse {
        public TransactionReceipt.Logs log;

        public byte[] id;

        public String field;

        public String value;
    }

    public static class OwnershipTransferredEventResponse {
        public TransactionReceipt.Logs log;

        public String previousOwner;

        public String newOwner;
        
        public byte[] txHash;
    }

    public static class ProductPurchasedEventResponse {
        public TransactionReceipt.Logs log;

        public byte[] id;

        public String buyer;

        public String seller;
    }

    public static class ProductDeletedEventResponse {
        public TransactionReceipt.Logs log;

        public byte[] id;

        public String reason;
    }

    // 辅助方法，处理asyncExecuteTransaction的返回值
    protected byte[] asyncExecuteTransactionWithByteReturn(Function function, TransactionCallback callback) {
        asyncExecuteTransaction(function, callback);
        return new byte[0]; // 返回一个空字节数组
    }
}
